"""
插件系统 - 支持动态加载和扩展
实现热插拔功能，提高系统的可扩展性
"""

import os
import sys
import importlib
import inspect
from typing import Dict, List, Type, Any, Optional
from pathlib import Path
import asyncio
from .interfaces import PluginInterface
from .config import config
from .events import event_bus, SystemEvents


class PluginManager:
    """
    插件管理器
    负责插件的加载、卸载、生命周期管理
    """
    
    def __init__(self):
        self._plugins: Dict[str, PluginInterface] = {}
        self._plugin_configs: Dict[str, Dict[str, Any]] = {}
        self._plugin_paths: List[Path] = []
        
    def add_plugin_path(self, path: str):
        """添加插件搜索路径"""
        plugin_path = Path(path)
        if plugin_path.exists():
            self._plugin_paths.append(plugin_path)
            if str(plugin_path) not in sys.path:
                sys.path.append(str(plugin_path))
                
    async def load_plugins_from_config(self):
        """从配置文件加载插件"""
        tools_config = config.get("tools", {})
        plugins_config = tools_config.get("plugins", {})
        
        for plugin_name, plugin_config in plugins_config.items():
            try:
                await self.load_plugin(plugin_name, plugin_config)
            except Exception as e:
                print(f"Failed to load plugin {plugin_name}: {e}")
                
    async def load_plugin(self, plugin_name: str, plugin_config: Dict[str, Any]):
        """
        加载单个插件
        
        Args:
            plugin_name: 插件名称
            plugin_config: 插件配置
        """
        if plugin_name in self._plugins:
            print(f"Plugin {plugin_name} already loaded")
            return
            
        # 获取插件类
        class_path = plugin_config.get("class")
        if not class_path:
            raise ValueError(f"Plugin {plugin_name} missing class configuration")
            
        try:
            # 动态导入插件类
            module_path, class_name = class_path.rsplit('.', 1)
            module = importlib.import_module(module_path)
            plugin_class = getattr(module, class_name)
            
            # 验证插件接口
            if not issubclass(plugin_class, PluginInterface):
                raise ValueError(f"Plugin {plugin_name} must implement PluginInterface")
                
            # 创建插件实例
            plugin_instance = plugin_class()
            
            # 初始化插件
            plugin_init_config = plugin_config.get("config", {})
            await plugin_instance.initialize(plugin_init_config)
            
            # 注册插件
            self._plugins[plugin_name] = plugin_instance
            self._plugin_configs[plugin_name] = plugin_config
            
            # 发布插件加载事件
            await event_bus.publish("plugin.loaded", {
                "plugin_name": plugin_name,
                "plugin_class": class_path
            })
            
            print(f"Plugin {plugin_name} loaded successfully")
            
        except Exception as e:
            await event_bus.publish("plugin.load_failed", {
                "plugin_name": plugin_name,
                "error": str(e)
            })
            raise
            
    async def unload_plugin(self, plugin_name: str):
        """卸载插件"""
        if plugin_name not in self._plugins:
            print(f"Plugin {plugin_name} not found")
            return
            
        try:
            plugin = self._plugins[plugin_name]
            await plugin.cleanup()
            
            del self._plugins[plugin_name]
            del self._plugin_configs[plugin_name]
            
            await event_bus.publish("plugin.unloaded", {
                "plugin_name": plugin_name
            })
            
            print(f"Plugin {plugin_name} unloaded successfully")
            
        except Exception as e:
            await event_bus.publish("plugin.unload_failed", {
                "plugin_name": plugin_name,
                "error": str(e)
            })
            raise
            
    async def reload_plugin(self, plugin_name: str):
        """重新加载插件"""
        if plugin_name in self._plugins:
            plugin_config = self._plugin_configs[plugin_name]
            await self.unload_plugin(plugin_name)
            await self.load_plugin(plugin_name, plugin_config)
        else:
            print(f"Plugin {plugin_name} not found")
            
    def get_plugin(self, plugin_name: str) -> Optional[PluginInterface]:
        """获取插件实例"""
        return self._plugins.get(plugin_name)
        
    def list_plugins(self) -> List[str]:
        """列出所有已加载的插件"""
        return list(self._plugins.keys())
        
    def discover_plugins(self, directory: str) -> List[str]:
        """发现指定目录下的插件"""
        plugins = []
        plugin_dir = Path(directory)
        
        if not plugin_dir.exists():
            return plugins
            
        for plugin_file in plugin_dir.glob("*.py"):
            if plugin_file.stem.startswith("plugin_"):
                try:
                    # 尝试导入模块
                    spec = importlib.util.spec_from_file_location(
                        plugin_file.stem, plugin_file
                    )
                    module = importlib.util.module_from_spec(spec)
                    spec.loader.exec_module(module)
                    
                    # 查找插件类
                    for name, obj in inspect.getmembers(module):
                        if (inspect.isclass(obj) and 
                            issubclass(obj, PluginInterface) and 
                            obj != PluginInterface):
                            plugins.append(plugin_file.stem)
                            break
                            
                except Exception as e:
                    print(f"Failed to discover plugin {plugin_file}: {e}")
                    
        return plugins
        
    async def cleanup_all(self):
        """清理所有插件"""
        for plugin_name in list(self._plugins.keys()):
            await self.unload_plugin(plugin_name)


# 全局插件管理器
plugin_manager = PluginManager()


def plugin_entry_point(name: str, version: str = "1.0.0"):
    """
    插件入口点装饰器
    
    Usage:
        @plugin_entry_point("github_analyzer", "1.0.0")
        class GitHubAnalyzerPlugin(PluginInterface):
            pass
    """
    def decorator(cls):
        # 添加插件元数据
        cls._plugin_name = name
        cls._plugin_version = version
        
        # 自动实现name和version属性
        if not hasattr(cls, 'name'):
            cls.name = property(lambda self: name)
        if not hasattr(cls, 'version'):
            cls.version = property(lambda self: version)
            
        return cls
    return decorator


class BasePlugin(PluginInterface):
    """
    插件基类 - 提供通用功能
    """
    
    def __init__(self):
        self._initialized = False
        self._config: Dict[str, Any] = {}
        
    @property
    def name(self) -> str:
        return getattr(self, '_plugin_name', self.__class__.__name__)
        
    @property
    def version(self) -> str:
        return getattr(self, '_plugin_version', '1.0.0')
        
    async def initialize(self, config: Dict[str, Any]):
        """初始化插件"""
        self._config = config
        await self._on_initialize()
        self._initialized = True
        
    async def cleanup(self):
        """清理资源"""
        await self._on_cleanup()
        self._initialized = False
        
    async def _on_initialize(self):
        """子类重写的初始化方法"""
        pass
        
    async def _on_cleanup(self):
        """子类重写的清理方法"""
        pass
        
    def get_config(self, key: str, default: Any = None) -> Any:
        """获取配置值"""
        return self._config.get(key, default)
        
    @property
    def is_initialized(self) -> bool:
        """检查是否已初始化"""
        return self._initialized